package xcmg.device.service.agent;

import com.github.pagehelper.PageInfo;
import org.apache.poi.ss.usermodel.CellType;
import yb.ecp.fast.infra.util.PageHelperPlus;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xcmg.device.dao.entity.agent.AgentAllotDO;
import xcmg.device.dao.entity.agent.AgentAllotDetailDO;
import xcmg.device.dao.entity.company.CompanyDealerDO;
import xcmg.device.dao.mapper.CompanyDealerMapper;
import xcmg.device.dao.mapper.CompanyInfoMapper;
import xcmg.device.dao.mapper.PriMaterialsMapper;
import xcmg.device.dao.mapper.agent.AgentAllotDetailMapper;
import xcmg.device.dao.mapper.agent.AgentAllotMapper;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.ExportUtil;
import xcmg.device.infra.FileUtil;
import xcmg.device.infra.ImportUtil;
import xcmg.device.infra.enums.BillDesc;
import xcmg.device.service.GenDocumentService;
import xcmg.device.service.basic.MaterialsService;
import xcmg.device.service.vo.FunctionResult;
import xcmg.device.service.vo.agent.AgentAllotAddVO;
import xcmg.device.service.vo.agent.AgentAllotDetailVO;
import xcmg.device.service.vo.agent.AgentAllotVO;
import xcmg.device.service.vo.agent.ExportDetailVO;
import xcmg.device.service.vo.basic.MaterialsVO;
import xcmg.device.service.warehouse.CommonService;
import xcmg.device.service.warehouse.WarehouseDeliveryService;
import xcmg.device.service.warehouse.WarehouseInboundService;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.util.ListUtil;
import yb.ecp.fast.infra.util.Ref;
import yb.ecp.fast.infra.util.StringUtil;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Service
public class AgentAllotService {

    @Autowired
    private AgentAllotMapper agentAllotMapper;

    @Autowired
    private AgentAllotDetailService agentAllotDetailService;

    @Autowired
    private AgentAllotDetailMapper agentAllotDetailMapper;

    @Autowired
    private GenDocumentService genDocumentService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private FastGenClient fastGenClient;

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private WarehouseInboundService warehouseInboundService;

    @Autowired
    private WarehouseDeliveryService warehouseDeliveryService;

    @Autowired
    private MaterialsService materialsService;

    @Autowired
    private CompanyDealerMapper companyDealerMapper;
    @Autowired
    private PriMaterialsMapper priMaterialsMapper;

    @Autowired
    private CompanyInfoMapper companyInfoMapper;

    @Value("${spring.file.download.path}")
    private String filePath;

    private String templateExcelFileName = "AgentTransferImport.xls";


    /**
     * 是否结算：0否 1是
     */
    private static final Integer IS_SETTLE_YES = 1;


    /**
     * @Author: WangKe
     * @Description: 生成代理商间调拨单
     * @Date: 2018/2/27 0027
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode add(AgentAllotAddVO agentAllotAddVO, String userId, String orgId) throws Exception {
        ActionResult<String> textResult = fastGenClient.textGuid();
        if (textResult.getCode() != ErrorCode.Success.getCode()) {
            return ErrorCode.IllegalArument;
        }
        AgentAllotVO agentAllotVO = agentAllotAddVO.getHeaderInfo();
        agentAllotVO.setId(textResult.getValue());
        agentAllotVO.setAllotOrder(genDocumentService.getDocumentNo(BillDesc.AgentAllot));
        agentAllotVO.setOrgId(orgId);
        agentAllotVO.setCreateId(userId);
        agentAllotVO.setCreateName(commonService.getUserName(userId));
        agentAllotVO.setCreateDate(new Date());
        agentAllotVO.setVerifyState(agentAllotAddVO.getHeaderInfo().getVerifyState());
        agentAllotVO.setInState(0);
        agentAllotVO.setOutState(0);

        CompanyDealerDO companyDealerDO = companyDealerMapper.itemByOrgId(orgId, agentAllotVO.getOutAgentId());
        if (companyDealerDO == null || StringUtil.isNullOrEmpty(companyDealerDO.getPlatOrgId())) {
            return ErrorCode.IllegalArument;
        }
        agentAllotVO.setOutAgentId(companyDealerDO.getPlatOrgId());
        companyDealerDO = companyDealerMapper.itemByOrgId(orgId, agentAllotVO.getInAgentId());
        if (companyDealerDO == null || StringUtil.isNullOrEmpty(companyDealerDO.getPlatOrgId())) {
            return ErrorCode.IllegalArument;
        }
        agentAllotVO.setInAgentId(companyDealerDO.getPlatOrgId());

        AgentAllotDO agentAllotDO = new AgentAllotDO();
        BeanUtils.copyProperties(agentAllotVO, agentAllotDO);
        boolean success = agentAllotMapper.insert(agentAllotDO) > 0;

        if (success) {
            //生成代理商间调拨详情记录
            List<AgentAllotDetailVO> detailVOList = agentAllotAddVO.getDetailList();
            if (ListUtil.isNullOrEmpty(detailVOList)) {
                return ErrorCode.IllegalArument;
            }

            BigDecimal costTotal = BigDecimal.ZERO;
            for (AgentAllotDetailVO detailVO : detailVOList) {
                detailVO.setAllotOrder(agentAllotVO.getAllotOrder());
                detailVO.setAllotId(agentAllotVO.getId());
                detailVO.setCreateId(agentAllotVO.getCreateId());
                detailVO.setCreateName(agentAllotVO.getCreateName());
                costTotal = costTotal.add(detailVO.getCostSubtotal() == null ? BigDecimal.ZERO : detailVO.getCostSubtotal());

                success = agentAllotDetailService.add(detailVO);
                if (!success) {
                    throw new Exception("生成代理商间调拨详情记录失败");
                }
            }

            success = updateAgentAllotCostPrice(agentAllotDO, costTotal);
        }
        return success ? ErrorCode.Success : ErrorCode.Failure;
    }

    /**
     * @Author: WangKe
     * @Description: 更新代理商间调拨单
     * @Date: 2018/2/27 0027
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode update(AgentAllotAddVO agentAllotAddVO, String orgId) throws Exception {
        AgentAllotVO allotVO = agentAllotAddVO.getHeaderInfo();
        List<AgentAllotDetailVO> detailVOList = agentAllotAddVO.getDetailList();

        if (allotVO == null || StringUtil.isNullOrEmpty(allotVO.getAllotOrder())) {
            return ErrorCode.IllegalArument;
        }
        if (allotVO.getVerifyState() == 2 || allotVO.getVerifyState() > 3) {
            return ErrorCode.AgentUpdateError;
        }
        AgentAllotDO agentAllotDO = new AgentAllotDO();
        BeanUtils.copyProperties(allotVO, agentAllotDO);
        boolean success = agentAllotMapper.updateByPrimaryKeySelective(agentAllotDO) > 0;
        if (success) {
            BigDecimal costTotal = BigDecimal.ZERO;
            agentAllotDetailMapper.removeByAllotOrderList(Arrays.asList(allotVO.getId()));
            for (AgentAllotDetailVO detailVO : detailVOList) {
                detailVO.setAllotOrder(allotVO.getAllotOrder());
                detailVO.setAllotId(allotVO.getId());
                detailVO.setCreateId(allotVO.getCreateId());
                detailVO.setCreateName(allotVO.getCreateName());
                costTotal = costTotal.add(detailVO.getCostSubtotal() == null ? BigDecimal.ZERO : detailVO.getCostSubtotal());

                success = agentAllotDetailService.add(detailVO);
                if (!success) {
                    return ErrorCode.Failure;
                }
            }

            success = updateAgentAllotCostPrice(agentAllotDO, costTotal);
        }

        return success ? ErrorCode.Success : ErrorCode.Failure;
    }

    /***
     * 修改成本总价
     * @param agentAllotDO
     * @param costTotal
     * @return
     */
    private boolean updateAgentAllotCostPrice(AgentAllotDO agentAllotDO, BigDecimal costTotal) {
        AgentAllotDO updateAgentAllotDO = new AgentAllotDO();
        updateAgentAllotDO.setVerifyState(null);
        updateAgentAllotDO.setOutState(null);
        updateAgentAllotDO.setInState(null);
        updateAgentAllotDO.setCostTotal(costTotal);
        updateAgentAllotDO.setId(agentAllotDO.getId());
        return agentAllotMapper.updateByPrimaryKeySelective(updateAgentAllotDO) > 0;
    }

    /**
     * @Author: WangKe
     * @Description: 更新代理商间调拨单状态
     * @Date: 2018/2/27 0027
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode updateSate(AgentAllotVO agentAllotVO, String userId) throws Exception {
        if (agentAllotVO == null || agentAllotVO.getId() == null || agentAllotVO.getVerifyState() == null) {
            return ErrorCode.IllegalArument;
        }
        AgentAllotDO agentAllotDO = agentAllotMapper.selectByPrimaryKey(agentAllotVO.getId());
        if (agentAllotDO == null) {
            return ErrorCode.IllegalArument;
        }
        if(agentAllotVO.getVerifyState().equals(agentAllotDO.getVerifyState())){
            return ErrorCode.IllegalArument;
        }
        agentAllotDO.setVerifyState(agentAllotVO.getVerifyState());
        agentAllotDO.setNote(agentAllotVO.getNote());
        agentAllotDO.setAuditUserId(userId);
        agentAllotDO.setAuditUserName(commonService.getUserName(userId));
        agentAllotDO.setAuditDate(new Date());
        boolean success = agentAllotMapper.updateByPrimaryKeySelective(agentAllotDO) > 0;
        if (success) {
            List<AgentAllotDetailDO> agentAllotDetailList = agentAllotDetailMapper.findByAllotOrderList(Arrays.asList(agentAllotDO.getId()));

            if (agentAllotVO.getVerifyState() == 2) {  //调出审核通过，生成出库事务单和入库事务单
                success = warehouseDeliveryService.saveByAgentAllotOut(agentAllotDO, agentAllotDetailList, userId, agentAllotDO.getOutAgentId());
                if (!success) {
                    throw new Exception("调出审核通过生成出库事物单时出错");
                }
                success = warehouseInboundService.saveByAgentAllotIn(agentAllotDO, agentAllotDetailList, userId, agentAllotDO.getInAgentId());
                if (!success) {
                    throw new Exception("调出审核通过生成入库事物单时出错");
                }
            }
//            else if(agentAllotVO.getVerifyState() == 5){  //调入审核驳回，删除入库事务单
//                WarehouseInboundAddVO inboundAddVO = warehouseInboundService.findByPK(agentAllotDO.getAllotOrder(), "order", agentAllotDO.getInAgentId());
//                if(inboundAddVO == null || inboundAddVO.getHeaderInfo() == null){
//                    throw new Exception("调入审核驳回，删除入库事务单时出错");
//                }
//                success = warehouseInboundService.delete(Arrays.asList(inboundAddVO.getHeaderInfo().getId()), agentAllotDO.getInAgentId()).getCode() == 0;
//                if(!success){
//                    throw new Exception("调入审核驳回，删除入库事务单时出错");
//                }
//            }
        }
        return ErrorCode.Success;
    }

    /**
     * @Author: WangKe
     * @Description: 删除代理商间调拨单
     * @Date: 2018/2/27 0027
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode remove(List<String> ids) throws Exception {
        if (agentAllotMapper.findNumForDelete(ids) > 0) {
            return ErrorCode.AgentDeleteError;
        }
        boolean success = agentAllotMapper.remove(ids) > 0;
        if (success) {
            success = agentAllotDetailMapper.removeByAllotOrderList(ids) > 0;
            if (!success) {
                throw new Exception("删除详情记录失败");
            }
        }
        return success ? ErrorCode.Success : ErrorCode.Failure;
    }

    /**
     * @Author: WangKe
     * @Description: 查询代理商间调拨单列表
     * @Date: 2018/2/27 0027
     */
    public PageCommonVO list(SearchCommonVO<AgentAllotVO> condition, String orgId) {
        PageCommonVO<AgentAllotVO> pageCommonVO = new PageCommonVO();
        PageHelperPlus.orderBy("create_date desc");
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        List<AgentAllotDO> doList = agentAllotMapper.list(condition.getFilters());
        List<AgentAllotVO> voList = new ArrayList<AgentAllotVO>();
        for (AgentAllotDO entity : doList) {
            AgentAllotVO model = new AgentAllotVO();
            BeanUtils.copyProperties(entity, model);
            //判断是创建人、调出方还是调入方
            if (orgId.equals(entity.getOrgId())) {
                model.setRoleType(0);
            } else if (orgId.equals(entity.getOutAgentId())) {
                model.setRoleType(1);
            } else if (orgId.equals(entity.getInAgentId())) {
                model.setRoleType(2);
            }
            voList.add(model);
        }
        pageCommonVO.setPageInfo(new PageInfo(doList));
        pageCommonVO.setPageInfoList(voList);
        return pageCommonVO;
    }

    /**
     * @Author: WangKe
     * @Description: 根据主键查找代理商间调拨单
     * @Date: 2018/2/27 0027
     */
    public AgentAllotAddVO findByPK(String id, String type, String orgId) {
        AgentAllotAddVO model = new AgentAllotAddVO();
        AgentAllotDO entity;
        if ("id".equals(type)) {
            entity = agentAllotMapper.selectByPrimaryKey(id);
        } else {
            entity = agentAllotMapper.selectByAllotOrder(id, orgId);
        }
        if (entity == null) {
            return null;
        }

        List<AgentAllotDetailDO> doList = agentAllotDetailMapper.findByAllotOrderList(Arrays.asList(entity.getId()));
        List<AgentAllotDetailVO> voList = new ArrayList<AgentAllotDetailVO>();
        if (CollectionUtils.isNotEmpty(doList)) {
            AgentAllotDetailVO AgentAllotDetailVO;
            for (AgentAllotDetailDO detailDO : doList) {
                AgentAllotDetailVO = new AgentAllotDetailVO();
                BeanUtils.copyProperties(detailDO, AgentAllotDetailVO);
                voList.add(AgentAllotDetailVO);
            }
        }
        AgentAllotVO agentAllotVO = new AgentAllotVO();
        BeanUtils.copyProperties(entity, agentAllotVO);
        //判断是创建人、调出方还是调入方
        if (orgId.equals(agentAllotVO.getOrgId())) {
            agentAllotVO.setRoleType(0);
        } else if (orgId.equals(agentAllotVO.getOutAgentId())) {
            agentAllotVO.setRoleType(1);
        } else if (orgId.equals(agentAllotVO.getInAgentId())) {
            agentAllotVO.setRoleType(2);
        }

        model.setHeaderInfo(agentAllotVO);
        model.setDetailList(voList);
        return model;
    }

    /**
     * @Author: WangKe
     * @Description: 导出代理商间调拨单
     * @Date: 2018/2/27 0027
     */
    public void export(List<String> ids, String orgId) throws Exception {
        invokeExport(agentAllotMapper.findByIds(ids), orgId);
    }

    /**
     * @Author: WangKe
     * @Description: 导出代理商间调拨单
     * @Date: 2018/2/27 0027
     */
    public void exportAll(AgentAllotVO condition, String orgId) throws Exception {
        List<AgentAllotDO> dataList = new ArrayList<>();
        PageHelperPlus.orderBy("create_date desc");
        dataList.addAll(agentAllotMapper.exportList(condition));
        invokeExport(dataList, orgId);
    }

    /**
     * @Author: WangKe
     * @Description: 导出代理商间调拨单
     * @Date: 2018/2/27 0027
     */
    private void invokeExport(List<AgentAllotDO> doList, String orgId) throws Exception {
        String title = "客户间调拨单据导出";
        String[] rowsName = new String[]{"序号", "调拨单号", "调拨角色", "调出客户", "调出状态", "调入客户",
                "调入状态", "发货日期", "制单日期", "制单部门", "制单人", "状态", "审核意见", "零件编号", "零件名称", "零件类型", "单位", "数量",
                "出库数量", "入库数量", "参考单价", "实际单价", "总价"};
        List<Object[]> dataList = new ArrayList<Object[]>();
        Object[] objs;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for (int i = 0; i < doList.size(); i++) {
            AgentAllotDO exportDO = doList.get(i);
            String roleName = "调入方";
            if (orgId.equals(exportDO.getOrgId())) {
                roleName = "创建方";
            } else if (orgId.equals(exportDO.getOutAgentId())) {
                roleName = "调出方";
            }
            objs = new Object[rowsName.length];
            objs[0] = i + 1;
            objs[1] = exportDO.getAllotOrder();
            objs[2] = roleName;
            objs[3] = exportDO.getOutAgentName();
            objs[4] = getState(exportDO.getOutState(), "完成");
            objs[5] = exportDO.getInAgentName();
            objs[6] = getState(exportDO.getInState(), "完成");
            objs[7] = exportDO.getDeliveryDate() == null ? "" : sdf.format(exportDO.getDeliveryDate());
            objs[8] = exportDO.getCreateDate() == null ? "" : sdf.format(exportDO.getCreateDate());
            objs[9] = exportDO.getDeptName();
            objs[10] = exportDO.getCreateName();
            objs[11] = getAuditState(exportDO.getVerifyState());
            objs[12] = exportDO.getNote();
            objs[13] = exportDO.getMaterialNo();
            objs[14] = exportDO.getMaterialName();
            objs[15] = exportDO.getMaterialType();
            objs[16] = exportDO.getUnit();
            objs[17] = exportDO.getAmount();
            objs[18] = exportDO.getOutAmount();
            objs[19] = exportDO.getInAmount();
            objs[20] = exportDO.getRefPrice();
            objs[21] = exportDO.getRealPrice();
            objs[22] = exportDO.getTotalPrice();
            dataList.add(objs);
        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }

    private String getState(Integer state, String title) {
        if (state == null) {
            state = 0;
        }
        if (state == 0) {
            return "未" + title;
        } else if (state == 1) {
            return "部分" + title;
        } else {
            return "已" + title;
        }
    }

    private String getAuditState(Integer state) {
        if (state == 0) {
            return "草稿";
        } else if (state == 1) {
            return "未完成";
        } else if (state == 2) {
            return "调出通过";
        } else if (state == 3) {
            return "调出驳回";
        } else if (state == 4) {
            return "调入通过";
        } else if (state == 5) {
            return "调入驳回";
        } else {
            return "";
        }
    }

    /**
     * @Author: WangKe
     * @Description: 零件批量导入
     * @Date: 2018/3/1 0001
     */
    public FunctionResult importExcel(InputStream in, String orgId) throws Exception {
        FunctionResult result = new FunctionResult();
        HSSFWorkbook wb = new HSSFWorkbook(in);
        HSSFSheet sheet = wb.getSheetAt(0);

        int totalRow = sheet.getLastRowNum();
        if (totalRow < 2) {
            result.setCode(ErrorCode.IllegalArument);
            result.setValue("导入模板不正确");
            return result;
        }
        int totalCell = sheet.getRow(1).getLastCellNum();
        if (totalCell != 5) {
            result.setCode(ErrorCode.IllegalArument);
            result.setValue("导入模板不正确");
            return result;
        }
        List<ExportDetailVO> detailVOList = new ArrayList<>();
        List<ExportDetailVO> errorDetailVOList = new ArrayList<>();
        for (int i = 2; i <= totalRow; i++) {
            HSSFRow curRow = sheet.getRow(i);
            ExportDetailVO detailVO = new ExportDetailVO();
            if (curRow == null) {
                continue;
            }
            String no = getCellValue(curRow, 0);
            String materialsNo = getCellValue(curRow, 1);
            String qty = getCellValue(curRow, 4);
            if (StringUtil.isNullOrEmpty(no) && StringUtil.isNullOrEmpty(materialsNo) && StringUtil.isNullOrEmpty(qty)) {
                continue;
            }
            if (StringUtil.isNullOrEmpty(no)) {
                detailVO.setErrorRow(i + 1);
                detailVO.setRemark("序号不能为空");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if (StringUtil.isNullOrEmpty(materialsNo)) {
                detailVO.setErrorRow(i + 1);
                detailVO.setRemark("零件编码不能为空");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if (StringUtil.isNullOrEmpty(qty)) {
                detailVO.setErrorRow(i + 1);
                detailVO.setRemark("申请数量不能为空");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if (!isInteger(qty) || "0".equals(qty)) {
                detailVO.setErrorRow(i + 1);
                detailVO.setRemark("申请数量格式不正确");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if (new BigDecimal(qty).compareTo(BigDecimal.valueOf(99999999.99)) > 0) {
                detailVO.setErrorRow(i + 1);
                detailVO.setRemark("申请数量过大");
                errorDetailVOList.add(detailVO);
                continue;
            }
            MaterialsVO materialsVO = materialsService.itemByNo(materialsNo, orgId);
            if (materialsVO == null) {
                detailVO.setErrorRow(i + 1);
                detailVO.setRemark("零件不存在");
                errorDetailVOList.add(detailVO);
                continue;
            }
            detailVO.setAmount(new BigDecimal(qty));
            detailVO.setMaterialsNo(materialsVO.getMaterialsNo());
            detailVO.setMaterialsDes(materialsVO.getMaterialsDes());
            detailVO.setMaterialType(materialsVO.getMaterialsType());
            detailVO.setUnit(materialsVO.getUnit());
            detailVO.setCostPrice(materialsVO.getStandardPrice());
            detailVO.setCostSubtotal(detailVO.getCostPrice() == null ? new BigDecimal(0) : detailVO.getCostPrice()
                    .multiply(detailVO.getAmount()));
            detailVOList.add(detailVO);
        }

        if (ListUtil.isNullOrEmpty(errorDetailVOList)) {
            result.setValue(ImportUtil.deRepeat(detailVOList, "MaterialsNo", "Amount", null, null));
            result.setCode(ErrorCode.Success);
        } else {
            result.setValue(errorDetailVOList);
            result.setCode(ErrorCode.IllegalArument);
        }
        return result;
    }

    private boolean isInteger(String str) {
        if (null == str || "".equals(str)) {
            return false;
        }
        try {
            BigDecimal decimal = new BigDecimal(str);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    private String getCellValue(HSSFRow curRow, int i) {
        String value = "";
        if (curRow.getCell(i) != null) {
            curRow.getCell(i).setCellType(CellType.STRING);
            value = curRow.getCell(i).getStringCellValue();
        }
        return value;
    }

    /**
     * @Author: WangKe
     * @Description: 下载零件批量导入模板
     * @Date: 2018/3/1 0001
     */
    public void download() throws Exception {
        FileUtil.downLoadFile(response, filePath, templateExcelFileName);
    }

    /**
     * 校验被添加的调拨信息是否有效<br>
     * 主要判断调出客户与物流之间的关系
     *
     * @param agentAllotAddVO AgentAllotAddVO
     * @param materialNos     Ref<List<String>> 错误的物流编码集合
     * @return ErrorCode
     */
    public ErrorCode checkCondition(AgentAllotAddVO agentAllotAddVO, Ref<List<String>> materialNos) {
        String outAgentId = agentAllotAddVO.getHeaderInfo().getOutAgentId();
        List<AgentAllotDetailVO> detailList = agentAllotAddVO.getDetailList();

        List<String> materialList = new ArrayList<>();

        if (ListUtil.isNullOrEmpty(detailList)) {
            return ErrorCode.IllegalArument;
        }

        for (AgentAllotDetailVO temp : detailList) {
            int ret = priMaterialsMapper.count(temp.getMaterialNo(), outAgentId);

            if (ret == 0) {
                materialList.add(temp.getMaterialNo());
            }
        }

        if (!ListUtil.isNullOrEmpty(materialList)) {
            materialNos.set(materialList);
            return ErrorCode.MaterialsNotExists;
        }
        return ErrorCode.Success;
    }

    /**
     * 手动完成单据<br>
     * materialsNo 不为null,则更改该单据下的零件状态为“手动完成”状态；如果materialsNo为空，则更改整个单据为“手动完成”状态
     *
     * @param billNo      String 单据编号
     * @param materialsNo String 零件编号
     * @param orgId       String 企业ID
     * @param type        操作类型（0入库操作，1出库操作）
     * @return ErrorCode 返回码
     */
    public ErrorCode manualFinish(String billNo, String materialsNo, String orgId, int type) {
        if (StringUtil.isNullOrEmpty(materialsNo))//零件编码为空，更新单据状态为“手动完成”
        {
            if (0 == type)//入库操作
            {
                agentAllotMapper.updateInStatus(3, billNo);
                warehouseInboundService.updateState(billNo, 3, orgId);
            } else  //出库操作
            {
                agentAllotMapper.updateOutStatus(3, billNo);
                warehouseDeliveryService.updateState(billNo, 3, orgId);
            }
        } else {
            if (0 == type)//入库操作
            {
                agentAllotDetailMapper.updateInStatus(3, billNo, materialsNo);
                warehouseInboundService.updateDetailState(billNo, materialsNo, null, 3, orgId);
                ErrorCode errorCode = checkBillFinished(billNo, orgId, type);

                if (ErrorCode.Success != errorCode) {
                    return errorCode;
                }
            } else {
                agentAllotDetailMapper.updateOutStatus(3, billNo, materialsNo);
                warehouseDeliveryService.updateDetailState(billNo, materialsNo, null, 3, orgId);
                ErrorCode errorCode = checkBillFinished(billNo, orgId, type);

                if (ErrorCode.Success != errorCode) {
                    return errorCode;
                }
            }
        }
        return ErrorCode.Success;
    }

    /**
     * 校验单据是否已完成<br>
     * 判断单据下的所有零件是否已经完成，如果都完成，则更改单据状态为完成
     *
     * @param billNo String
     * @param orgId  String
     * @param type   操作类型（0入库操作，1出库操作）
     * @return Boolean
     */
    private ErrorCode checkBillFinished(String billNo, String orgId, int type) {
        boolean flag = true;
        List<AgentAllotDetailDO> detailDOs = agentAllotDetailMapper.listByBillNo(billNo, orgId);

        if (0 == type) {
            for (AgentAllotDetailDO temp : detailDOs) {
                if (2 == temp.getInState() || 3 == temp.getInState()) {
                    //完成状态
                    continue;
                }
                flag = false;
            }
            if (flag) {
                agentAllotMapper.updateInStatus(3, billNo);
                warehouseInboundService.updateState(billNo, 3, orgId);
            }
        } else {
            for (AgentAllotDetailDO temp : detailDOs) {
                if (2 == temp.getOutState() || 3 == temp.getOutState()) {
                    //完成状态
                    continue;
                }
                flag = false;
            }
            if (flag) {
                agentAllotMapper.updateOutStatus(3, billNo);
                warehouseDeliveryService.updateState(billNo, 3, orgId);
            }
        }

        return ErrorCode.Success;
    }

    /**
     * 结算
     *
     * @param agentAllotVO
     * @return
     */
    public int settle(AgentAllotVO agentAllotVO) {
        AgentAllotDO agentAllotDO = new AgentAllotDO();
        BeanUtils.copyProperties(agentAllotVO, agentAllotDO);
        agentAllotDO.setIsSettle(IS_SETTLE_YES);
        agentAllotDO.setSettleTime(new Date());
        return agentAllotMapper.updateByPrimaryKeySelective(agentAllotDO);
    }
}
